﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TransportAbstractionLibrary;
using System.IO;
using TransportAbstractionLibrary.Exceptions;

namespace Test
{
    class FileSender : IProtocolUpperLayer
    {
        Guid id = new Guid("FBA09E43-E1E2-4984-9524-9C10A7AA7982");
        
        IProtocolLowerLayer lowerLayer;
        Stream sourceStream;
        int bufferSize;

        //constructor
        public FileSender(string file)
        {
            sourceStream = File.OpenRead(file);
            bufferSize = 1024 * 10;
        }

        public FileSender(Stream source)
        {
            this.sourceStream = source;
            bufferSize = 1024 * 10;
        }

        public FileSender(string file, int bufferSize)
        {
            sourceStream = File.OpenRead(file);
            this.bufferSize = bufferSize;
        }

        public FileSender(Stream source, int bufferSize)
        {
            this.sourceStream = source;
            this.bufferSize = bufferSize;
        }

        #region IProtocolUpperLayer Members

        void IProtocolUpperLayer.Bind(IProtocolLowerLayer lowerLayer)
        {
            if (this.lowerLayer == null)
            {
                this.lowerLayer = lowerLayer;
            }
            else
            {
                throw new ArgumentException("Already bound!");
            }
        }

        void IProtocolUpperLayer.Receive(byte[] data)
        {
            Console.WriteLine("Receive");
            //thay want more data!
            SendData();
        }

        public IProtocolLowerLayer LowerLayer
        {
            get { return lowerLayer; }
        }

        void IProtocolUpperLayer.OnException(TALException talException)
        {
            Console.WriteLine("Exception occured: " + talException.ToString());
        }

        void IProtocolUpperLayer.ConnectionClosed()
        {
            Console.WriteLine("Connection closed!");
        }

        #endregion

        #region IProtocolBase Members

        public Guid Id
        {
            get { return id; }
        }

        void IProtocolBase.Initialize()
        {
            Console.WriteLine("Initialize");
            //lets read some data and send it'
            SendData();
        }

        private void SendData()
        {
            //check if EOF
            if (sourceStream.Position == sourceStream.Length)
            {
                //we are done!
                Console.WriteLine("File sent!");
                Dispose();
            }
            else
            {
                Console.WriteLine("Sending data!");
                byte[] buffer = new byte[Math.Min(bufferSize, sourceStream.Length - sourceStream.Position)];
                sourceStream.Read(buffer, 0, buffer.Length);
                lowerLayer.Send(buffer);
            }
        }

        bool IProtocolBase.SuppressInitialization
        {
            get { return lowerLayer.SuppressInitialization; }
        }

        public LayerType LayerType
        {
            get
            {
                if (lowerLayer != null)
                {
                    return lowerLayer.LayerType | LayerType.Top;
                }
                else
                {
                    return LayerType.Top;
                }
            }
        }
        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            sourceStream.Dispose();
            lowerLayer.Dispose();
        }

        #endregion

    }
}
